// types.hpp : Defines basic types (vectors, ray, color), and operations on it.
//

#ifndef TYPES_HPP_INCLUDE
#define TYPES_HPP_INCLUDE

#include <iostream>

using namespace std;

class Vector3 {
private:
	double x_, y_, z_;
public:
	Vector3(double x = 0, double y = 0, double z = 0);
	Vector3(double xyz[3]) : x_(xyz[0]), y_(xyz[1]), z_(xyz[2]) {}
	Vector3(float xyz[3]) : x_(xyz[0]), y_(xyz[1]), z_(xyz[2]) {}
	friend ostream& operator<<(ostream& os, const Vector3& dt);

	double getX() const;
	double getY() const;
	double getZ() const;
	void setX(double x);
	void setY(double Y);
	void setZ(double Z);

	Vector3 operator+(const Vector3& arg) const;
	Vector3 operator-(const Vector3& arg) const;
	Vector3 operator*(const Vector3& arg) const;
	Vector3 operator*(double arg) const;
	friend double dot(const Vector3& v1, const Vector3& v2);
	friend double mod(const Vector3& v);
	friend Vector3 normalize(const Vector3& v);
};

class Ray
{
private:
	Vector3 origin_, direction_;
public:
	Ray(Vector3 origin, Vector3 direction);
	friend ostream& operator<<(ostream& os, const Ray& dt);
	Vector3 getOrigin() const;
	Vector3 getDirection() const;
};

class Color
{
private:
	double r_, g_, b_;
public:
	Color(double r = 1.0, double g = 1.0, double b = 1.0);
	Color operator*(const Color& c) const;
	Color operator*(double k) const;
	Color operator+(const Color& c) const;
	double getR() const;
	double getG() const;
	double getB() const;
	friend ostream& operator<<(ostream& os, const Color& dt);
};


// Value object for texture coordinates
class TexCoords
{
public:
	typedef float CoordType;

	TexCoords() {}
	TexCoords(CoordType u, CoordType v) : _u(u), _v(v) {}
	TexCoords(const TexCoords& orig) : _u(orig._u), _v(orig._v) {}

	TexCoords& operator = (const TexCoords& right)
		{ _u = right._u; _v = right._v; return *this; }

	__declspec(property(get = GetU)) CoordType U;
	__declspec(property(get = GetV)) CoordType V;
	CoordType GetU() const { return _u; }
	CoordType GetV() const { return _v; }

private:
	CoordType _u, _v;
};

/*class BBox
{
private:
	Vector3 min_, max_;
public:
	BBox(Vector3 v);

	BBox operator+(const Vector3& b) const;
};*/

#endif //TYPES_HPP_INCLUDE